package shuzhi.excel;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

import com.alibaba.fastjson.JSONObject;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import jodd.io.findfile.WildcardFindFile;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import shuzhi.excel.Excel.Config.SheetConfig;

@Slf4j
@Component
@Order(1)
public class Excel implements ApplicationRunner {

	@Override
	public void run(ApplicationArguments args) throws Exception {
		File path = new File(ResourceUtils.getURL("classpath:").getPath());
		String jarPath = path.getAbsolutePath().split("file:")[0];
//		String jarPath = "D:\\ProgramFiles\\eclipse\\excle_sz\\target";// demo
//		String jarPath = "/Users/chenwenxi/git/excle_sz/target";// demo
		final File excelFolderSources = new File(jarPath + File.separator + "excel_sources");
		final File excelFolderTarget = new File(jarPath + File.separator + "excel_target");
		final File excelFolderConfig = new File(jarPath + File.separator + "excel_config");
		this.mkdir(excelFolderSources, excelFolderTarget, excelFolderConfig);
		Config config = this.getConfigAndtouch(excelFolderConfig);
		List<File> findAllExcelFiles = this.findAllExcelFiles(excelFolderSources);
		findAllExcelFiles.forEach(excel -> {
			this.doExcel(config, excel, excelFolderTarget);
		});

		this.exit("提取完成!!!");
	}

	private void doExcel(Config config1, File excelFile, File excelFolderTarget) {
		List<List<Object>> resultAll = new ArrayList<>();
		config1.getSheetConfigs().forEach(config -> {
			if (!Optional.ofNullable(config).map(SheetConfig::get工作表).isPresent()) {
				this.exit("没有配置工作表");
			}
			if (!Optional.ofNullable(config).map(SheetConfig::get要拆分的列).isPresent() || config.get要拆分的列().size() == 0) {
				this.exit("没有配置提取列表项");
			}
			log.info("提取配置:", config.toString());
			Integer get工作表 = config.get工作表() - 1;// sheet从0开始算,要减去1
			log.info("解析文件:" + excelFile.getName());
			List<Integer> columns = config.get要拆分的列();
			Integer columnBySplit = columns.get(0);// 一个sheet只有一个列需要拆分

			ExcelReader reader = ExcelUtil.getReader(excelFile, get工作表);
			List<List<Object>> read = reader.read();
			List<List<Object>> result = read.stream().map(list -> {// 循环每一行
				List<Object> temp = new ArrayList<>();
				for (int i = 0; i < list.size(); i++) {
					Object column = list.get(i);
					temp.add(column);
					if (i == columnBySplit - 1) {
						this.splitColumn(column, temp);
					}
				}
				return temp;
			}).collect(Collectors.toList());

			resultAll.addAll(result);
		});
		resultAll.forEach(a->{
			System.out.println(a);
		});
		this.renameTitle(resultAll);//修改标题
		log.info("生成excel...");
		ExcelWriter writer = ExcelUtil.getWriter(StrUtil.format("{}/{}{}{}", excelFolderTarget,
				FileUtil.getName(excelFile), DateUtil.format(new Date(), "yyyyMMdd_HHmmss"), ".xlsx"));
		writer.setColumnWidth(0, 12);
		writer.setColumnWidth(1, 29);
		writer.setColumnWidth(2, 11);
		writer.setColumnWidth(8, 45);
		writer.setColumnWidth(10, 80);
		writer.write(resultAll, true);
		writer.close();
		log.info("生成excel完成...");
	}
	/**
	 * 修改标题
	 * @param resultAll
	 */
	private void renameTitle(List<List<Object>> resultAll) {
		List<Object> remove = resultAll.remove(0);
		remove.add(2, "");
		remove.add(3, "");
		remove.add(4, "A");
		remove.add(5, "B");
		resultAll.add(0, remove);
	}
	/**
	 * 拆分型号该列
	 * @param column
	 * @param temp
	 */
	private void splitColumn(Object column, List<Object> temp) {
		// 找到拆分列
		List<String> split = new ArrayList<>();
		split.addAll(Arrays.asList(column.toString().split(" ")));
		for (int i = 0; i < 5 - split.size(); i++) {//如果数据不足5则填充到5
			split.add(" ");
		}
		for (int i = 0; i < split.size(); i++) {
			String string = split.get(i);
			if (i == 0) {
				temp.add(string);
			} else if (i == 1) {
				temp.add(string);
			} else if (i == 2) {
				if (string.startsWith("A")) {
					temp.add(string.substring(1, string.length()));
				}
			} else if (i == 3) {
				if (string.startsWith("B")) {
					temp.add(string.substring(1, string.length()));
				}
			}
		}
	}

	/**
	 * 找出要提取的所有xls
	 * 
	 * @param excelFolderSources
	 * @return
	 */
	private List<File> findAllExcelFiles(File excelFolderSources) {
		List<File> findAllExcelFiles = WildcardFindFile.create().include("**.xls*").matchOnlyFileName()
				.searchPath(excelFolderSources.getAbsolutePath()).findAll();
		log.info("找到excel文件数量:{}", findAllExcelFiles.size());
		findAllExcelFiles.forEach(f -> {
			log.info("- ", f.getName());
		});
		return findAllExcelFiles;
	}

	/**
	 * 获取配置文件,如果文件删除则创建默认配置文件
	 * 
	 * @param folderConfig
	 * @throws IOException
	 */
	private Config getConfigAndtouch(File folderConfig) throws IOException {
		File fileConfig = new File(folderConfig.getAbsolutePath() + File.separator + "config.json");
		if (!jodd.io.FileUtil.isExistingFile(fileConfig)) {
			jodd.io.FileUtil.writeString(fileConfig, JSONUtil.toJsonPrettyStr(getADemo()));
		}
		return JSONObject.parseObject(jodd.io.FileUtil.readString(fileConfig), Config.class);
	}

	/**
	 * 批量创建所需的文件夹
	 * 
	 * @param folders
	 */
	private void mkdir(File... folders) {
		Arrays.asList(folders).forEach(folder -> {
			log.info("检查资源目录是否存在:{}", folder.getAbsoluteFile());
			if (!FileUtil.isDirectory(folder)) {
				FileUtil.mkdir(folder);
				log.info("不存在,创建:{}", folder.getAbsoluteFile());
			}
		});
	}

	@Data
	public static class Config {
		private List<SheetConfig> sheetConfigs;

		@Data
		public static class SheetConfig {
			private Integer 工作表;
			private List<Integer> 要拆分的列;
		}
	}

	public static void main(String[] args) {
		System.out.println(JSONUtil.toJsonPrettyStr(getADemo()));
	}

	private void exit(String errorMsg) {
		log.info("退出操作:" + errorMsg);
		System.exit(1);
	}

	public static Config getADemo() {
		Config config = new Config();
		SheetConfig sheetConfig = new Config.SheetConfig();
		sheetConfig.set工作表(1);
		sheetConfig.set要拆分的列(Arrays.asList(2));
		config.setSheetConfigs(Arrays.asList(sheetConfig));
		return config;
	}

}